
if(!window.Berta) window.Berta = {};

Berta.Controller = function() {
	
	return {
		
		options: {
		},
		
		listeners: {},
		
		// getter: returns event namespace for the instance
		namespace: function() { return '.Berta.Controller'; },
		_: function(callback) { var self = this; return function() { return callback.apply(self, arguments); }; },
		
		//   .______    __    __  .______    __       __    ______    ////////////////////////////////////////////////////////////
		//   |   _  \  |  |  |  | |   _  \  |  |     |  |  /      |   ////////////////////////////////////////////////////////////
		//   |  |_)  | |  |  |  | |  |_)  | |  |     |  | |  ,----'   ////////////////////////////////////////////////////////////
		//   |   ___/  |  |  |  | |   _  <  |  |     |  | |  |        ////////////////////////////////////////////////////////////
		//   |  |      |  `--'  | |  |_)  | |  `----.|  | |  `----.   ////////////////////////////////////////////////////////////
		//   | _|       \______/  |______/  |_______||__|  \______|   ////////////////////////////////////////////////////////////
				
		init: function() {
			$(window).bind('unload'+this.namespace(), this._(cleanup));
			$('#cleanupButton').bind('click'+this.namespace(), this._(cleanup));
			this._(initPlugins)();
			this._(initObjects)();
		},
		
		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		//  A P I   /////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

		/* executes a command
		 * command is in the form: <instance>:<method>, e.g., editorManager:create
		 * all the remaining arguments are passed to the method
		 */
		execCommand: function(command /*, args... */) {	// TODO: make safer!
			setTimeout(this.execCommandDo, 1, this, command, arguments);
		},
		execCommandDo: function(self, command, args) {
			var c = command.split(':');
			if(c[0] === 'controller') {
				self.execOwnCommand.apply(self, args);
			}
			
			if(self.hasOwnProperty(c[0])) {
				Array.prototype.shift.call(args);
				self[c[0]][c[1]].apply(self[c[0]], args);
			}
		},
		
		execOwnCommand: function(commandTitle) {
			switch(commandTitle) {
				case 'controller:reloadMenuHTML':
					var oldMenu = $('.x-mainmenu'), self = this;
					oldMenu.animate({ opacity: 0 }, 100, function() {
						Berta.Server.instance().get(Berta.Route.get('get:snippet-menu'), function(xhrId, response) {
							var newMenu = $(response.text).css({ opacity: 0 });
							oldMenu.after(newMenu).empty().remove();
							newMenu.animate({ opacity: 1 }, 300);
						});
					});
					break;
				
				case 'controller:reloadEditable':
					var oldEl = $(arguments[1]), route = arguments[2], self = this;
					oldEl.bertaEditableOff().animate({ opacity: 0 }, 100, function() {
						Berta.Server.instance().get(route, function(xhrId, response) {
							if(response.text) {
								var newEl = $(response.text).hide();
								self.fireEvent('beforeEditableReload', [ oldEl.get(0), newEl.get(0) ]);
								oldEl.after(newEl).detach();
								
								newEl.css({ opacity: 0 }).show().animate({ opacity: 1 }, 900).bertaEditableOn();
								self.fireEvent('afterEditableReload', [ oldEl.get(0), newEl.get(0) ]);
								oldEl.empty().remove();
							} else {
								alert('cannot reload element!');
								oldEl.animate({ opacity: 1 }, 100).bertaEditableOn();
							}
						});
					});
			}
		}, 
		
		addEvent: function(eventName, listener) {
			if(!this.listeners[eventName]) this.listeners[eventName] = [];
			this.listeners[eventName].push(listener);
		},
		removeEvent: function(eventName, listener) {
			if(this.listeners[eventName] && this.listeners[eventName].length > 0) {
				if (!listener) {
					this.listeners[eventName] = [];
				} else {
					for (var i = 0; i < this.listeners[eventName].length; i++) {
						if (this.listeners[eventName][i] == listener) {
							this.listeners.splice(i, 1);
						}
					}
				}
			}
		},
		fireEvent: function(eventName, params) {
			if (this.listeners[eventName] && this.listeners[eventName].length > 0) {
				for (var i = 0; i < this.listeners[eventName].length; i++) {
					this.listeners[eventName][i].apply(window, params);
				}
			}
		}
	};
	
	
	//   .______   .______     __  ____    ____  ___   .___________. _______    //////////////////////////////////////////////////
	//   |   _  \  |   _  \   |  | \   \  /   / /   \  |           ||   ____|   //////////////////////////////////////////////////
	//   |  |_)  | |  |_)  |  |  |  \   \/   / /  ^  \ `---|  |----`|  |__      //////////////////////////////////////////////////
	//   |   ___/  |      /   |  |   \      / /  /_\  \    |  |     |   __|     //////////////////////////////////////////////////
	//   |  |      |  |\  \--.|  |    \    / /  _____  \   |  |     |  |____    //////////////////////////////////////////////////
	//   | _|      | _| `.___||__|     \__/ /__/     \__\  |__|     |_______|   //////////////////////////////////////////////////

	
	/**
	 * Sets some important settings for some jquery plugins used
	 */
	function initPlugins() {
		// INIT JQUERY PLUGINS...
		$.debug(true);
		//$.metadata.setType("html5"); // replaced by .data() 
	}
	
	
	/**
	 * Inits all Berta objects
	 */
	function initObjects() {
		
		// INIT CLIENT_SIDE STORAGE
		// client-side session storage
		Berta.Storage.instance();
		
		// INIT SERVER...
		// the layer for communication with the server (REST, file post/get, etc.)
		Berta.Server.instance();
		
		// SETTINGS
		// keeps all settings and their definitions client-side
		// downloads them once from the server, and then stores them in local session storage (if available)
		var s = Berta.Settings.instance();
		
		// LOAD SETTINGS, and continue when all needed are loaded
		var settingsQueue = [
		    'definitions.settings',
		    'values.settings',
		    'definitions.template-settings.' + Berta.Options.template_id,
		    'values.template-settings.' + Berta.Options.template_id
		];
		s.load(settingsQueue, this._(initObjects2));
	}
	function initObjects2() {
		// EDITORMANAGER manages all .x-editable instances on the page,
		// as well as creates new and deletes the existing by API
		Berta.EditorManager.instance();
		
		// SETTINGS RENDERER...
		// makes DOM elements for each setting (caption + editable + ...)
		Berta.SettingsRenderer.instance();
		
				
		// INIT PANEL...   MEMORY LEAKS!!!!! FIX !!!!! (still leaking? test test..)
		Berta.Panel.instance();
		
		
		this.articles = new Berta.Articles();
		
		// turn on the articles
		this.articles.on();
		
		// register editables for the page
		// (the panel registers its editables on its own)
		// (articles do, too)
		Berta.EditorManager.instance().registerEditables('.x-editable:not(#xBertaPanel .x-editable):not(.x-article .x-editable)', 'page');


		// Instantiate grid
		Berta.Grid.instance();

	}
	
	/**
	 * Cleans up stuff on page unload
	 */
	function cleanup() {
		$.log('Berta.Controller: cleanup');
		jQuery('*').unbind();
		
		$.log('cleanup server');
		Berta.Server.instance().cleanup();
		$.log('cleanup editorManager');
		Berta.EditorManager.instance().destroyAll();
		$.log('cleanup panel');
		Berta.Panel.instance().destroy();	
		
		this.listeners = null;
	}
	
}();